use salvo::{conn::TcpListener, serve_static::StaticDir, Listener, Router, Server as Salvo};
use std::{
    ffi::{c_char, CStr, CString},
    fmt::format,
};
use tokio::{
    runtime::Runtime,
    sync::OnceCell,
    task::{self, JoinHandle},
};

pub struct Server {
    pub runtime: Runtime,
    task: Option<JoinHandle<()>>,
}

impl Server {
    pub fn new() -> Server {
        let runtime = tokio::runtime::Builder::new_multi_thread()
            .enable_all()
            .build()
            .unwrap();

        Server {
            runtime,
            task: None,
        }
    }

    pub unsafe fn listen(&mut self, path: *const c_char, port: i32) {
        let path = CStr::from_ptr(path).to_str().unwrap();

        let _ = self.runtime.enter();
        let task = self.runtime.spawn(async move {
            let router = Router::with_path("<*path>").get(
                StaticDir::new([path])
                    .include_dot_files(false)
                    .defaults("index.html")
                    .auto_list(true),
            );

            let acceptor = TcpListener::new(&format!("0.0.0.0:{}", port)).bind().await;
            Salvo::new(acceptor).serve(router).await;
        });
        self.task = Some(task);
    }
}
